/*********************************************************************************
 *      Copyright:  (C) 2019 Wu Yujun<540726307@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  at_cmd.c
 *    Description:  This file send at command
 *                 
 *        Version:  1.0.0(2019年07月04日)
 *         Author:  Wu Yujun <540726307@qq.com>
 *      ChangeLog:  1, Release initial version on "2019年07月04日 18时23分02秒"
 *                 
 ********************************************************************************/
#include "at_cmd.h"
#include "get_apn.h"


#define     REPLY_LEN       512

/*****************************************************
 *  描述: 发送 AT+CPIN? 命令到GPRS模块来检查sim卡是否到位
 *
 *  返回值： 
 *          成功返回0  失败返回负数
 *************************************************************/
int atcmd_check_sim_present(st_comport *comport)
{
    int         rv = 0; 
    char        rev_buf[REPLY_LEN];

    rv = send_cmd(comport, "AT+CPIN?\r", rev_buf, sizeof(rev_buf), 760);
    if(rv < 0 )
    {
        printf("AT+CPIN? check SIM present FAILED\n");
        return rv;
    }
    if(strstr(rev_buf, "READY"))
    {
        printf("AT+CPIN? check SIM present OK\n");
        return 0;
    }
    else
        return -1;
}

/*****************************************************
 *  描述: 发送 AT+CSQ 命令到GPRS模块来检查sim卡信号
 *
 *  返回值： 
 *          成功返回信号值  失败返回负数
 *************************************************************/
int atcmd_check_sim_signal(st_comport *comport)
{
    int                 rv = 0; 
    char                rev_buf[REPLY_LEN];
    char                *ptr = NULL ;
    int                 csq ;
    int                 signal = -1;

    rv = send_cmd(comport, "AT+CSQ\r", rev_buf, sizeof(rev_buf), 820);
    if(rv < 0 )
    {
        printf("AT+CSQ check SIM signal FAILED\n");
        goto cleanup;
    }
    ptr = strstr(rev_buf,"CSQ:") ; //+CSQ: 6,99
    if(!ptr)
    {
        printf("CSQ are not compared\n") ;
        goto cleanup ;
    }
    ptr = ptr + 5 ;
    if(ptr == NULL)
    {
        goto cleanup ;
    }
    csq = atoi(ptr) ;
    //printf("Cmp = [%s] atoi csq = %d\n", cmp, csq) ;
    if(csq < 2 || csq >=99)
    {
        printf("No signal\n") ;
        goto cleanup ;
    }
    signal = csq ;
cleanup :
    return signal ;
}


/*****************************************************
 *  描述: 发送 AT+COPS? 命令到GPRS模块来检查sim卡信号
 *  输出值： 
 *      oprator_buf返回运营商名称
 *  返回值： 
 *          成功返回0  失败返回负数
 *************************************************************/
int atcmd_check_sim_operator(st_comport *comport , char *operator_buf, int buf_size)
{
    int                 rv = -1; 
    char                rev_buf[REPLY_LEN];
    char                *ptr = NULL,*ptr_end = NULL;
    char                cmp[128] ;
    int                 n = 0 ;

    if(!operator_buf || buf_size <= 0)
    {
        printf("Invail input paremeter in %s\n", __FUNCTION__) ;
        goto cleanup ;
    }
    rv = send_cmd(comport, "AT+COPS?\r", rev_buf, sizeof(rev_buf), 1000);
    if(rv < 0 )
    {
        printf("AT+COPS? check SIM operator FAILED\n");
        rv = -2 ;
        goto cleanup;
    }
    ptr = strstr(rev_buf,"\"") ;//+COPS: 0,0,"CHN-UNICOM",2
    if(!ptr)
    {
        printf("Operator are not compared\n") ;
        rv = -4 ;
        goto cleanup ;
    }
    ptr = ptr+1 ;
    ptr_end = strstr(ptr,"\"") ;
    ptr_end = ptr_end + 1 ;
    n = abs((ptr_end-ptr)) ;
    snprintf(cmp,n,"%s",ptr) ;
    strncpy(operator_buf,cmp,buf_size) ;
    rv = 0 ;

cleanup: 
        return rv ;
}


/*****************************************************
 *  描述: 发送 AT+CIMI 命令到GPRS模块获取IMSI
 *
 *  输出值：
 *          15位IMSI值以字符串形式返回imsi_buf
 *  返回值： 
 *          成功返回0  失败返回负数
 *************************************************************/
int atcmd_check_sim_imsi(st_comport *comport , char *mcc_buf,int mcc_size,char *msn_buf,int msn_size)
{
    int                 rv = -1; 
    char                rev_buf[REPLY_LEN];
    char                *ptr = NULL ;
    char                cmp[64] ;
    int                 find = 0 ;

    if(!mcc_buf || !msn_buf || mcc_size< 3 || msn_size < 2)
    {
        printf("Invail input paremeter in %s\n", __FUNCTION__) ;
        rv = -1 ;
        goto cleanup ;
    }
    rv = send_cmd(comport, "AT+CIMI\r", rev_buf, sizeof(rev_buf), 1320);
    if(rv < 0 )
    {
        printf("AT+CIMI check SIM IMSI FAILED\n");
        goto cleanup;
    }
    //IMSI是15位的十进制数。其结构如下：MCC(共3位,中国为460)+MNC(用于识别移动用户所归属的移动通信网，2~3位)+MSIN
    ptr = strstr(rev_buf,"CIMI") ;
    if(!ptr)
    {
        printf("string are not compared\n") ;
        rv = -2 ;
        goto cleanup ;
    }
    while(ptr != NULL)
    {

        if(*ptr >='0'&&*ptr<='9')
        {
            find = 1 ;
            break ;
        }
        ptr = ptr+1 ;
    }
    if(!find)
    {
        printf("can't find CIMI!\n") ;
        rv = -3 ;
        goto cleanup ;
    }
    memset(cmp,0,sizeof(cmp)) ;
    snprintf(cmp,16,"%s", ptr) ;
    printf("IMSI:%s\n",cmp) ;
    snprintf(mcc_buf, 4,"%s",cmp) ;
    strncpy(msn_buf, cmp+3, 2) ;
    rv = 0 ;

cleanup:
    return rv ;


}



/*****************************************************
 *  描述: 发送 AT+CPSI? 命令到GPRS模块来获取sim卡MCC与MNC
 *
 *  返回值： 
 *          成功返回0  失败返回负数
 *************************************************************/
int atcmd_check_sim_location(st_comport *comport, char *mcc_mnc, int size)
{
    int                 rv = 0; 
    char                rev_buf[REPLY_LEN];
    char                *ptr_start = NULL ;
    char                *ptr_end = NULL ;

    if( comport == NULL || mcc_mnc == NULL || size <= 0 )
    {
        printf("Invail parameter in %s\n", __FUNCTION__) ;
        return -1 ;
    }

    rv = send_cmd(comport, "AT+CPSI?\r", rev_buf, sizeof(rev_buf), 880);
    if(rv < 0 )
    {
        printf("AT+CPSI? check SIM cpsi FAILED\n");
        goto cleanup ;
    }
    /*  +CPSI: WCDMA,Online,460-01,0xE105,142927634,WCDMA IMT 2000,449,10688,0,5.5,99,25,9,500  */
    ptr_start = strstr(rev_buf,"+CPSI:") ;
    if(ptr_start == NULL)
    {
        printf("string are not compared\n") ;
        rv = -2 ;
        goto cleanup ;
    }
    ptr_start = strstr(ptr_start,",") ; //,Online,460-01,0xE105...
    if(ptr_start == NULL)
        return -3 ;
    ptr_start =ptr_start + 1 ;
    ptr_start = strstr(ptr_start,",") ;//,460-01,0xE105...
    if(ptr_start == NULL)
        return -4 ;
  
    ptr_start = ptr_start+1 ;
    ptr_end = ptr_start ;//460-01,0xE105...
    if(ptr_end == NULL)
        return -5 ;
    ptr_end  = strstr(ptr_end,",") ;//ptr_end = ,0xE105...
    if(ptr_end == NULL)
        return -6 ;

    strncpy( mcc_mnc, ptr_start, (ptr_end-ptr_start)) ;
    if(strlen(mcc_mnc) == 0)
    {
        printf("get mcc_mnc failed\n") ;
        return -7 ;
    }

    rv = 0 ;
cleanup:
    return rv ;
 
}



/*****************************************************
 *  描述: 发送 AT+CREG? 命令到GPRS模块来检查sim卡网络注册情况
 *
 *  返回值： 
 *          成功返回0  失败返回负数
 *************************************************************/
int atcmd_check_sim_creg(st_comport *comport)
{
    int                 rv = 0; 
    char                rev_buf[REPLY_LEN];
    char                *ptr = NULL ;
    char                cmp[64] ;
    int                 creg = -1 ;

    rv = send_cmd(comport, "AT+CREG?\r", rev_buf, sizeof(rev_buf), 880);
    if(rv < 0 )
    {
        printf("AT+CREG? check SIM creg FAILED\n");
        goto cleanup;
    }
    ptr = strstr(rev_buf,"CREG:") ; //+CREG: 0,1
    if(!ptr)
    {
        printf("string are not compared\n") ;
        rv = -2 ;
        goto cleanup ;
    }
    ptr = strstr(rev_buf,",") ;
    ptr =ptr + 1 ;
    memset(cmp,0, sizeof(cmp)) ;
    snprintf(cmp,2,"%s" ,ptr) ;
    creg = atoi(cmp) ;
    /*    +CREG :<mode>,<stat> [,<lac>,<ci>]  <stat> 0：未注册，终端当前并未在搜寻新的运营商 1：已注册本地网络
     *         *   2：未注册，终端正在搜寻基站 4：未知代码 5：已注册，处于漫游状态*/
    if(creg !=1 && creg !=5)
    {
        printf("sim no register\n") ;
        rv =  -3 ;
        goto cleanup ;
    }
    printf("AT+CREG? Sim card net register OK\n") ;
    rv = 0 ;
cleanup:
    return rv ;

}

/***************************************  
 *  描述：发短信
 *  参数：name通过哪个AT接口发送
 *  返回值：
 *          成功返回0, 失败返回负数
 * ***************************************/
int send_mess(const char *name,const char *phone_num,const char *sms) 
{

    int             rv = 0 ;
    char            rbuf[1024] ;
    char            mess[512] ;
    char            at_cmgs[128] ;
    st_comport      *comport = NULL ;

    if(name == NULL || phone_num == NULL || sms ==NULL)
    {
        printf("Invail input parameter in %s\n", __FUNCTION__) ;
        return -1 ;
    }
    comport = comport_init(name, 115200,8,'N',1,'N') ;
    if(!comport)
    {
        printf("comport_init() failed\n") ;
        rv = -1 ;
        goto cleanup;
    }
    comport->fd = open_comport(comport) ;
    if(comport->fd < 0)
    {
        printf("Open_comport() Failed\n") ;
        rv = -2 ;
        goto cleanup ;
    }

    /*     设置信息格式为TEXT方式  */
    rv = send_cmd(comport, "AT+CMGF=1\r", rbuf, sizeof(rbuf), 800);
    if(rv < 0 )
    {
        printf("AT+CMGS FAILED\n");
        rv = -3 ;
        goto cleanup;
    }

    memset(at_cmgs,0,sizeof(at_cmgs)) ;
    snprintf(at_cmgs, sizeof(at_cmgs),"AT+CMGS=\"%s\"\r", phone_num) ;
    rv = send_cmd(comport, at_cmgs, rbuf, sizeof(rbuf), 1200);
    if(rv < 0)
    {
        printf("AT+CMGS FAILED\n");
        rv = -4 ;
        goto cleanup;
    }

    memset(mess, 0, sizeof(mess));
    snprintf(mess, sizeof(mess), "%s",sms) ;
    strcat(mess,"\x1a");
    rv = send_cmd(comport, mess, rbuf, sizeof(rbuf), 3500);
    if(rv < 0 )
    {
        printf("send message FAILED\n");
        rv = -5 ;
        goto cleanup;
    }
    if(!strstr(rbuf, "OK"))
    {
        printf("Send Message Failed\n") ;
        rv = -6 ;
        goto cleanup ;
    }

    rv = 0 ;
cleanup:
        comport_term(comport) ;
    return rv ;
}

/****************************************************************************************
 *  描述：发PDU格式短信短信
 *  参数：AT_inter通过哪个AT接口发送，len实际发送长度,pdu_sms是PDU格式装包之后的发送内容
 *  返回：
 *      成功返回0， 失败返回负数
 ****************************************************************************************/
int send_pdu_sms(const char *AT_inter, int len, char *pdu_sms)
{
    int             rv = 0 ;
    char            rbuf[1024] ;
    char            mess[512] ;
    char            at_cmgs[64] ;
    st_comport      *comport = NULL ;


    if(AT_inter == NULL || len <= 0 || pdu_sms == NULL)
    {
        printf("Invail input parameter in %s\n", __FUNCTION__) ;
        return -1 ;
    }
    comport = comport_init(AT_inter, 115200,8,'N',1,'N') ;
    if(!comport)
    {
        printf("comport_init() failed\n") ;
        rv = -1 ;
        goto cleanup;
    }
    comport->fd = open_comport(comport) ;
    if(comport->fd < 0)
    {
        printf("Open_comport() Failed\n") ;
        rv = -1 ;
        goto cleanup ;
    }

    /*     设置信息格式为PDU方式  */
    rv = send_cmd(comport, "AT+CMGF=0\r", rbuf, sizeof(rbuf), 800);
    if(rv < 0 )
    {
        printf("AT+CMGS FAILED\n");
        rv = -3 ;
        goto cleanup;
    }

    memset(at_cmgs,0,sizeof(at_cmgs)) ;
    /* AT+CMGS=${sms_len} */
    snprintf(at_cmgs, sizeof(at_cmgs),"AT+CMGS=%d\r", len) ;
    rv = send_cmd(comport, at_cmgs, rbuf, sizeof(rbuf), 800);
    if(rv < 0)
    {
        printf("AT+CMGS FAILED\n");
        rv = -4 ;
        goto cleanup;
    }

    memset(mess, 0, sizeof(mess));
    snprintf(mess, sizeof(mess), "%s",pdu_sms) ;
    strcat(mess,"\x1a");
    rv = send_cmd(comport, mess, rbuf, sizeof(rbuf), 3500);
    if(rv < 0 )
    {
        printf("send message FAILED\n");
        rv = -5 ;
        goto cleanup;
    }
    if(!strstr(rbuf, "OK"))
    {
        printf("Send Message Failed\n") ;
        rv = -6 ;
        goto cleanup ;
    }

    rv = 0 ;
cleanup:
        comport_term(comport) ;
    return rv ;
}

/****************************************************************************************
 *  描述：  检查未读短信
 *  输入参数：
 *      st_comport结构体类型指针，int *index用于输出短信位置的数组，index_size数组大小
 *
 *  输出参数：
 *      int 类型数组index[]，返回短信位置的数组
 *  返回：
 *      成功返回未读短信数，失败返回负数
 ***************************************************************************************/
int check_unread_mess(st_comport *comport, int *index, int index_size)
{
    int         rv = -1 ;
    char        rev_buf[512] ;
    char        *ptr ;
    int         find = 0 ;

    int         where[255] ;
    int         num = 0 ;
    int         i = 0 ;


    if( !comport || !index || index_size < 1 )
    {
        printf("Invail input paremeter in %s\n", __FUNCTION__) ;
        return -1 ;
    }

    memset(rev_buf, 0, sizeof(rev_buf) );

    rv = send_cmd(comport, "AT+CMGL=\"REC UNREAD\"\r", rev_buf, sizeof(rev_buf), 1000) ; 
    if(rv < 0)
    {
        printf("send cmd AT+CMGL=\"REC UNREAD\" failed\n") ;
        return -1 ;
    }

    memset(where, 0, sizeof(where) ) ;

    num = 0 ;
    ptr = rev_buf ; 
    /*  AT+CMGL="REC UNREAD"
     *  +CMGL: 0,"REC UNREAD","18934935550","","19/07/24,13:16:29+32"
     *  hello world*/
    while( *ptr ) //while *ptr no equal the last of string '\0'
    {   

        find = 0 ;
        ptr = strstr(ptr, "+CMGL:") ;
        if(ptr == NULL)
        {
            printf("all message already read\n") ;
            break ;
        }
        ptr = strstr(ptr, ":") ;//+CMGL: 0,"REC UNREAD",... 
        ptr = ptr + 1 ;
        while( *ptr )
        {
            if(*ptr == ' ') //skip space find index
            {
                ptr = ptr + 1 ;
            }
            else
            {
                if( *ptr>='0' && *ptr<= '9') //find index number
                {
                    find = 1 ;
                    break ;
                }
            }
        }
        if(find == 0)
        {
            printf("can't find index\n") ;
            return -3 ;
        }
        where[num] = atoi(ptr) ;
        num ++ ;
    }
    if(num == 0) //all message already read
    {
        return -4 ;
    }
    if(num > index_size)
    {
        printf("parameter index too small, message index:\n") ;
        for(i=0; i < num; i++)
        {
            printf("[%d]",where[i]) ;
        }
        printf("\n") ;
        return -4 ;
    }
    for(i = 0; i < num; i++)
    {
        index[i] = where[i] ;
    }
    return num ;
}

/****************************************************************************************
 *  描述：  2019/7/31,发送AT+CMGL="ALL"或AT+CMGL="REC UNREAD"列出短信
 *  输入参数：
 *      st_comport结构体类型指针，int *index用于输出短信位置的数组，index_size数组大小,
 *      type == UNREAD/ALL 
 *
 *  输出参数：
 *      int 类型数组index[]，返回短信位置的数组
 *  返回：
 *      成功返回短信数，失败返回负数
 ***************************************************************************************/
int check_cmgl(st_comport *comport, int *index, int index_size, int type)
{
    int         rv = -1 ;
    char        rev_buf[512] ;
    char        *ptr ;
    int         find = 0 ;

    int         where[255] ;
    int         num = 0 ;
    int         i = 0 ;
    char        cmd[64] ;


    if( !comport || !index || index_size < 1 )
    {
        printf("Invail input paremeter in %s\n", __FUNCTION__) ;
        return -1 ;
    }
    /*   List sms by text format  */
    rv = send_cmd(comport, "AT+CMGF=1\r", rev_buf, sizeof(rev_buf), 1000) ; 
    if(rv < 0)
    {
        printf("send cmd AT+CMGF failed\n") ;
        return -1 ;
    }

    memset(cmd, 0, sizeof(cmd)) ;
    snprintf(cmd, sizeof(cmd), "AT+CMGL=\"%s\"\r", type==UNREAD?"REC UNREAD":"ALL") ;
    memset(rev_buf, 0, sizeof(rev_buf) );
    rv = send_cmd(comport, cmd, rev_buf, sizeof(rev_buf), 1000) ; 
    if(rv < 0)
    {
        printf("send cmd AT+CMGL failed\n") ;
        return -2 ;
    }

    memset(where, 0, sizeof(where) ) ;

    num = 0 ;
    ptr = rev_buf ; 
    /*  AT+CMGL="REC UNREAD"
     *  +CMGL: 0,"REC UNREAD","18934935550","","19/07/24,13:16:29+32"
     *  hello world*/
    while( *ptr ) //while *ptr no equal the last of string '\0'
    {   

        find = 0 ;
        ptr = strstr(ptr, "+CMGL:") ;
        if(ptr == NULL)
        {
            printf("all message already read\n") ;
            break ;
        }
        ptr = strstr(ptr, ":") ;//+CMGL: 0,"REC UNREAD",... 
        ptr = ptr + 1 ;
        while( *ptr )
        {
            if(*ptr == ' ') //skip space find index
            {
                ptr = ptr + 1 ;
            }
            else
            {
                if( *ptr>='0' && *ptr<= '9') //find index number
                {
                    find = 1 ;
                    break ;
                }
            }
        }
        if(find == 0)
        {
            printf("can't find index\n") ;
            return -3 ;
        }
        where[num] = atoi(ptr) ;
        num ++ ;
    }
    if(num == 0) //all message already read
    {
        return -4 ;
    }
    if(num > index_size)
    {
        printf("parameter index too small, message index:\n") ;
        for(i=0; i < num; i++)
        {
            printf("index[%d]",where[i]) ;
        }
        printf(" have sms\n") ;
        return -4 ;
    }
    for(i = 0; i < num; i++)
    {
        index[i] = where[i] ;
    }
    return num ;
}


/********************************************************************************************************
 *  描述：  读取短信
 * 
 *  输入参数：
 *      comport是指向st_comport类型的指针，int index是读取短信的位置，int size是输错参数字符串的大小
 *
 *  输出参数：
 *      rec_buf用于输出收到的短信内容
 *          
 *  返回值：
 *      成功返回0， 失败返回负数
 *
 ****************************************************************************************************/
int read_sms(st_comport *comport,int index,char *rec_buf, int rec_size) 
{

    int     rv = -1 ;
    char    cmd[64] ;
    char    buf[512] ;

    char    *ptr = NULL ;
    int     len = 0 ;

    if( !comport || !rec_buf || rec_size <= 0 || index < 0 )
    {
        printf("Invail input paremeter in %s\n",__FUNCTION__) ;
        return -1 ;
    }

    memset(cmd, 0, sizeof(cmd)) ;
    snprintf(cmd, sizeof(cmd), "AT+CMGR=%d\r", index) ;

    memset(buf, 0, sizeof(buf)) ;
    rv = send_cmd(comport, cmd, buf, sizeof(buf), 1000) ;
    if(rv < 0)
    {
        printf("send cmd %s fail\n", cmd) ;
        return -2 ;
    }
    /*
     *  +CMGL: 0,"REC UNREAD","18934935552","","19/07/24,12:09:39+32"
     *  receive message
     *
     *  OK
     **/
    ptr = strstr(buf, "+CMGR:") ;    
    if(ptr == NULL)
    {
        printf("Can't find CMGR") ;
        return -3 ;
    }
    ptr = strstr(ptr,",") ;
    ptr = ptr + 1 ;
    if(ptr == NULL)//return "phone number",""."time" message
    {
        return -3 ;
    }
    len = strlen(ptr) ;
    len = len -5 ;//ignore the last <CR>OK<CR><CR>
    if(rec_size < len)
    {
        printf("receive size too small\n") ;
        return -4 ;
    }


    strncpy(rec_buf, ptr, len) ;
    return 0 ;
}



/*********************************************
 *  描述：删除短信
 *
 *  参数：index 删除短信的位置
 * 
 *  返回值：
 *        成功返回0, 失败返回负数
 ************************************************/
int delete_sms(st_comport *comport ,int index)
{
    int     rv = -1 ; 
    char    cmd[32] ;

    char    rev_buf[128] ;

    if( !comport || index < 0 )
    {
        printf("Invail input parameter in %s\n",__FUNCTION__);
        return -1 ;
    }
    memset(cmd, 0, sizeof(cmd)) ;
    snprintf(cmd, sizeof(cmd), "AT+CMGD=%d\r", index) ;

    memset(rev_buf, 0, sizeof(rev_buf)) ;
    rv = send_cmd(comport, cmd, rev_buf, sizeof(rev_buf), 1000) ;
    if(rv < 0)
    {
        printf("send cmd %s failed\n", cmd) ;
        return -2 ;
    }

    return 0 ;
}

/* ***************************************
 * 描述：检查Sim卡是否注册上 
 *
 * 参数：const char *name通过哪个AT接口去发送AT命令去检查
 *      st_gsmd_ctx结构体用来赋值注册情况如：信号注册商等
 * 返回值：
 *      需要声明头文件gsmd.h,成功返回OK,失败返回其他 
 * *************************************************************/
int check_regsiter(const char *name,st_gsmd_ctx *gsmd_ctx)
{
    int                 rv = -1 ;
    int                 signal = -1;

    if(!name)
    {
        printf("invail paremeter in %s\n",__FUNCTION__) ;
        rv = -1 ;
        goto cleanup ;
    }


    gsmd_ctx->comport = comport_init(name, 115200,8,'N',1,'N') ;
    if(!gsmd_ctx->comport)
    {
        printf("comport_init() failed\n") ;
        rv = OPEN_ERROR ;
        goto cleanup;
    }
    gsmd_ctx->comport->fd = open_comport(gsmd_ctx->comport) ;
    if(gsmd_ctx->comport->fd < 0)
    {
        printf("Open_comport() Failed\n") ;
        rv = OPEN_ERROR ;
        goto cleanup ;
    }
    /*    检查SIM卡是否到位      */
    rv = atcmd_check_sim_present(gsmd_ctx->comport) ;
    if(rv != 0)
    {
        printf("SIM present NO_IN\n") ;
        rv = NOT_IN ;
        gsmd_ctx->gsmRegInfo.sim_present = NOT_IN ;
        goto cleanup ;
    }
    gsmd_ctx->gsmRegInfo.sim_present = OK ;


    /*    检查信号强度       */
    signal = atcmd_check_sim_signal(gsmd_ctx->comport) ;
    if(signal < 0)
    {
        printf("ERROR signal!\n") ;
        rv = NO_SIGNAL ;
        gsmd_ctx->gsmRegInfo.sim_signal = 0 ;
        goto cleanup ;
    }
    gsmd_ctx->gsmRegInfo.sim_signal = signal ;

    /*    查看运营商      */
    rv = atcmd_check_sim_operator(gsmd_ctx->comport,gsmd_ctx->gsmRegInfo.operater, sizeof(gsmd_ctx->gsmRegInfo.operater )) ;
    if(rv < 0) 
    {
        printf("Check operator ERROR\n") ;
        rv = NO_CREG ;
        goto cleanup ;
    }
    printf("SIM card Operator:[%s]\n",gsmd_ctx->gsmRegInfo.operater) ;

    /*    检查IMSI       */
#if 0

    /* IMSI是15位的十进制数。其结构如下：MCC(共3位,中国为460)+MNC(用于识别移动用户所归属的移动通信网，2~3位)+MSIN */ 
    rv = atcmd_check_sim_imsi(gsmd_ctx->comport, gsmd_ctx->gsmRegInfo.mcc_buf, 
            sizeof(gsmd_ctx->gsmRegInfo.mcc_buf), gsmd_ctx->gsmRegInfo.msn_buf,
            sizeof(gsmd_ctx->gsmRegInfo.msn_buf)) ;
    if(rv < 0)
    {
        printf("ERROR IMSI\n") ;
        rv = ERROR_IMSI ; 
        goto cleanup ;
    }
#endif
    rv = atcmd_check_sim_location(gsmd_ctx->comport, gsmd_ctx->gsmRegInfo.mcc_mnc, sizeof(gsmd_ctx->gsmRegInfo.mcc_mnc)) ;
    if(rv < 0)
    {
        printf("ERROR IMSI\n") ;
        rv = ERROR_IMSI ; 
        goto cleanup ;
    }

    //printf("GSM sim card MCC:%s MSN:%s\n",gsmd_ctx->gsmRegInfo.mcc_buf, gsmd_ctx->gsmRegInfo.msn_buf) ;

    /*    检查网络注册情况     */

    rv = atcmd_check_sim_creg(gsmd_ctx->comport) ;
    if(rv != 0)
    {
        printf("ERROR CREG\n") ;
        rv = NO_CREG ;
        gsmd_ctx->gsmRegInfo.sim_register = NO_CREG ;
        goto cleanup ;
    }

    rv = get_apn_conf(DEFAULT_APN_CONF, gsmd_ctx->gsmRegInfo.mcc_mnc, &(gsmd_ctx->gsmRegInfo.simapn), APN_3G) ;
    if(rv < 0)
    {
        printf("ERROR GET APN\n") ;
        rv = NO_CREG ;
        gsmd_ctx->gsmRegInfo.sim_register = NO_CREG ;
        goto cleanup ;
    
    }
    gsmd_ctx->gsmRegInfo.sim_register = OK ;

    rv = OK ;
    printf("\nGSM Module signal: %d, Operater [%s], MCC_MNC[%s] APN[%s] User[%s] Pwd[%s]\n",gsmd_ctx->gsmRegInfo.sim_signal, 
            gsmd_ctx->gsmRegInfo.operater, gsmd_ctx->gsmRegInfo.mcc_mnc, 
            gsmd_ctx->gsmRegInfo.simapn.apn, gsmd_ctx->gsmRegInfo.simapn.uid, gsmd_ctx->gsmRegInfo.simapn.pwd) ;
cleanup:
    gsmd_ctx->gsmRegInfo.ready = rv ; 
    comport_term(gsmd_ctx->comport) ;

    /*         End Of Main      */
    return rv ;
}


/* *******************************************
 * 描述：发送AT命令
 *
 * 参数：st_comport *comport指向串口相关结构体st_comport的指针
 *       char *cmd是需要发送的AT命令
 *       char *buf传入字符串用于接收GPRS模块返回的信息
 *       int buf_size字符串的大小
 *       int timeout 传入超时时间
 *输出值：
        buf返回发送AT命令后对应的GPRS返回的内容
 *
 * 返回值：
 *         成功返回0，失败返回负数 
 * *********************************************/
int  send_cmd(st_comport *comport, char *cmd, char *buf, int buf_size, int timeout)
{
    int             rv = -1 ;
    int             cmd_length = 0 ;
    char            at_rev[1024] ;

    if(comport->fd <0)
    {
        printf("com port isn't opened\n") ;
        rv = -1 ;
        goto cleanup ;
    }
    if(( cmd == NULL) || (buf == NULL) || (buf_size <= 0))
    {
        printf("Invail input parameter!\n") ;
        rv = -2 ;
        goto cleanup ;
    }
    rv = read_comport(comport, at_rev, sizeof(at_rev), 100) ; //写串口前先读一下串口，防止有数据没读出来
    if(rv < 0&& rv != TIMEOUT) //读出错并且不是因为超时读不到数据
    {
        printf("read from other side failure %d: %s\n",rv, strerror(errno)) ;
        rv = -3 ;
        goto cleanup ;
    }//如果是超时说明没有数据，有数据读出来后丢弃
    memset(at_rev, 0 , sizeof(at_rev));

    cmd_length = strlen(cmd) ;
    if( (rv = write_comport(comport, cmd, cmd_length))< 0)
    {
        printf("write to other side failure %d :%s\n",rv, strerror(errno)) ;
        rv = -4 ;
        goto cleanup  ;
    }
    usleep(1000*timeout) ;//写串口，延时一段时间再读
    rv = read_comport(comport, at_rev, sizeof(at_rev), 1000) ;
    if(rv < 0)
    {
        printf("read from other side failure %d: %s\n",rv, strerror(errno)) ;
        rv = -4 ;
        goto cleanup ;
    }
    //printf("Read From gprs:%s\n",at_rev) ;
    if(strstr(at_rev,"ERROR")) //发送AT命令成功的会返回OK, 返回ERROR说明出错。
    {
        printf("AT Receive ERROR\n") ;
        rv = -5 ;
        goto cleanup ;
    }
    strncpy(buf, at_rev, buf_size) ;
    rv = 0 ;    

cleanup:
    return rv ;
}

